許多panic產生的原因是由於程式沒寫好造成的
下面談談幾個常見的陷阱
Golang的array和slice有別,slice無法確定內容元素的數量。
用index的方式(限定數字)去取得slice的指定元素是可以,不過千萬要小心,擁有元素的數量小於指定的index,就會發生錯誤。
若要用此用法,最好先判斷slice長度,可保平安。
if len(peopleLine) >= 11 {
b := peopleLine[10]
fmt.Println("b is:", b)
}
Map 型態的變數可以先用var宣告出來,也可以指定index進行賦值,編譯時也不會報錯。但是未先用make或其他方式宣告記憶體,執行程式下去會立刻炸出panic送你。
使用map,記得事先用make建立。
gaintMap := make(meowMap, 0)
gaintMap["a"] = "aa"
有次為了紀錄程式log,貪圖方便,竟妄想一行把錯誤資訊串在字串方便記錄,結果疏忽了,錯誤資訊也要發生錯誤才會有,從nil去取得Error()的內容,無疑的程式不丟panic給你才怪。
注意.Error 只在判斷有err發生的範圍使用
if err != nil {
err.Error()
}
nil pointer 的錯誤也很常發生,其實上面提到的三個常見錯誤,廣義上他們也是屬於某種nil pointer。
常見的情形,是發生在當你取得method返回值型態,不是單純的int、string、float64這種,而是比較複雜的slice、map、或者struct、interface甚至function,可能就要特別留意。
如果發生問題,回傳值很可能是拿到預設值而已,試想一下,slice、map的預設值是什麼?這篇文章提到slice和map可能發生的panic是什麼情形造成的,各位看倌就可想而知了。
若回傳的型態是struct、interface、function,發生問題時可能這整個東西都是nil(預設值唄),或者內容是預設值(指struct),nil當然就不能呼叫你想使用的函式,就如前一點的錯誤情形類似,一但使用就死定了。
我認為這件事情,是當你在撰寫method是否會有error回傳的時候,就需要停下來稍微思考和決定,當真的有錯誤發生和回傳的時候,接下的程式該怎麼去做,在Golang寫了一段時間後,可能潛移默化地且自然而然,四處想到使用error作為處理上的判斷,但也請將思考接到錯誤的後續處理,也練成自然而然有仔細考慮的習慣。
這個追根究底也是nil pointer的問題,而且造成原因與上面所述沒什麼兩樣,有些人喜歡用defer的方式,在發生錯誤或者某些判斷,離開所在的function時執行某些動作,然後要呼叫函式執行某些動作,前提是你也要先有實體才行,沒有實體先出來,或因為發生錯誤導致沒有實體化,執行到這段也是只有發生panic的命。
如下面示意,你確定離開function時,這個connector並非是nil嗎?或者Close()是有實體的嗎?
defer connector.Close()
下篇談談不同gotuine對map的操作,這可就是fatal error了,而不是panic可以復原......